import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QMenuBar, QMenu, QAction, qApp, QVBoxLayout, QTextBrowser, \
    QHBoxLayout, QPushButton, QLineEdit, QWidget, QLabel, QTableWidget, QComboBox, QTableWidgetItem, QSizePolicy, QGraphicsOpacityEffect
import pandas as pd
from PyQt5.QtCore import QRegExp
from PyQt5.QtGui import QRegExpValidator

page_number_list = ['5', '10', '20', '50', '100']

class MainWidget(QWidget):
    def __init__(self):
        super().__init__()
        # self.key = key
        self.page_number = '10'  # 每页条数
        self.current_page = 1  # 当前页码
        self.table_data = [[]]
        self.table_title = []
        self.total_page = 0
        self.show_pages = 5  # 显示多少可视页数
        self.page_number_index = [i for i, item in enumerate(page_number_list) if item == self.page_number]  # 可选的每页条数
        self.table = QTableWidget()
        self.first = QPushButton('首页')
        self.first.clicked.connect(lambda: self.page_change(1))
        self.last = QPushButton('尾页')
        self.last.clicked.connect(lambda: self.page_change(self.total_page))
        self.previous = QPushButton('上一页')
        self.previous.clicked.connect(lambda: self.page_change(self.current_page - 1))
        self.follow = QPushButton('下一页')
        self.follow.clicked.connect(lambda: self.page_change(self.current_page + 1))
        self.btn1 = QPushButton('1')
        self.btn2 = QPushButton('2')
        self.btn3 = QPushButton('3')
        self.btn4 = QPushButton('4')
        self.btn5 = QPushButton('5')
        # self.btn1.setVisible(True)
        # self.btn2.setVisible(True)
        # self.btn3.setVisible(True)
        # self.btn4.setVisible(True)
        # self.btn5.setVisible(True)
        self.btn1.clicked.connect(self.page_click)
        self.btn2.clicked.connect(self.page_click)
        self.btn3.clicked.connect(self.page_click)
        self.btn4.clicked.connect(self.page_click)
        self.btn5.clicked.connect(self.page_click)
        self.btn1.setFixedSize(40, 40)
        self.btn2.setFixedSize(40, 40)
        self.btn3.setFixedSize(40, 40)
        self.btn4.setFixedSize(40, 40)
        self.btn5.setFixedSize(40, 40)
        self.page_number_box = QComboBox()
        self.total_page_text = QLabel(f'共 {self.total_page_count()} 页')
        self.per_page_front = QLabel('每页')
        self.per_page_after = QLabel('条')
        self.front_label = QLabel('跳转到')
        self.after_label = QLabel('页')
        self.page_number_box.addItems(page_number_list)
        self.page_number_box.setCurrentIndex(self.page_number_index[0])
        self.page_number_box.currentIndexChanged.connect(self.page_number_changed)
        self.access_page = QLineEdit()

        self.init_ui()

    def init_ui(self):
        self.init_params()
        vbox = QVBoxLayout()
        page_box = QHBoxLayout()

        self.access_page.setFixedWidth(50)
        self.access_page.returnPressed.connect(lambda: self.page_change(int(self.access_page.text())))
        # 设置只能输入数字
        reg_int = QRegExp("^-?\\d+$")
        self.access_page.setValidator(QRegExpValidator(reg_int))

        page_box.addStretch()
        page_box.addWidget(self.first)
        page_box.addWidget(self.previous)
        page_box.addWidget(self.btn1)
        page_box.addWidget(self.btn2)
        page_box.addWidget(self.btn3)
        page_box.addWidget(self.btn4)
        page_box.addWidget(self.btn5)
        page_box.addWidget(self.follow)
        page_box.addWidget(self.last)
        page_box.addWidget(self.total_page_text)
        page_box.addWidget(self.per_page_front)
        page_box.addWidget(self.page_number_box)
        page_box.addWidget(self.per_page_after)
        page_box.addWidget(self.front_label)
        page_box.addWidget(self.access_page)
        page_box.addWidget(self.after_label)

        vbox.addWidget(self.table)
        vbox.addLayout(page_box)
        vbox.addStretch()

        self.setLayout(vbox)
        self.setGeometry(100, 100, 1920, 1340)
        self.flash_page_components()

    def show_and_hidden(self):
        if self.btn2.isVisible():
            self.btn2.setVisible(False)
        else:
            self.btn2.setVisible(True)

    def page_click(self):
        """
        页码按钮点击事件
        :return:
        """
        # 获取触发信号的按钮对象
        button = self.sender()
        self.current_page = self.set_current_page(int(button.text()))
        self.flash_data()
        self.flash_buttons()
        self.flash_page_components()

    def set_current_page(self, page):
        """
        设置当前页页码
        :param page: 传入的页码
        :return: int
        """
        if page <= 0:
            page = 1
            self.access_page.setText('1')
        if page > self.total_page:
            page = self.total_page
            self.access_page.setText(str(self.total_page))
        return page

    def set_current_page_style(self):
        self.btn1.setStyleSheet("")
        self.btn2.setStyleSheet("")
        self.btn3.setStyleSheet("")
        self.btn4.setStyleSheet("")
        self.btn5.setStyleSheet("")
        if self.btn1.text() == str(self.current_page):
            self.set_style(self.btn1)
        if self.btn2.text() == str(self.current_page):
            self.set_style(self.btn2)
        if self.btn3.text() == str(self.current_page):
            self.set_style(self.btn3)
        if self.btn4.text() == str(self.current_page):
            self.set_style(self.btn4)
        if self.btn5.text() == str(self.current_page):
            self.set_style(self.btn5)

    @staticmethod
    def set_style(btn):
        """
        给按钮设置样式
        :param btn: 按钮
        :return:
        """
        btn.setStyleSheet("""
                        QPushButton {
                            background-color: blue;
                            border: none;
                            color: white;
                            padding: 10px 24px;
                            text-align: center;
                            text-decoration: none;
                            font-size: 16px;
                            margin: 0;
                            border-radius: 8px;
                        }

                        QPushButton:hover {
                            background-color: #45a049;
                        }

                        QPushButton:pressed {
                            background-color: #3e8e41;
                        }
                    """)

    def page_change(self, next_page):
        """
        首页、尾页、上一页、下一页、跳转到第几页触发事件
        :param next_page:
        :return:
        """
        self.current_page = self.set_current_page(next_page)
        self.flash_data()
        self.flash_buttons()
        self.flash_page_components()

    def resize_columns(self):
        """
        重置列宽
        :return: 无返回值
        """
        self.table.resizeColumnsToContents()

    def init_params(self):
        """
        初始化按钮参数
        :return:
        """
        data = [
            ["Alice", 25, "New York"],
            ["Bob", 30, "London"],
            ["Charlie", 35, "Tokyo"],
            ["Bob", 30, "London"],
            ["Charlie", 35, "Tokyo"],
            ["Bob", 30, "London"],
            ["Charlie", 35, "Tokyo"],
            ["Bob", 30, "London"],
            ["Charlie", 35, "Tokyo"],
            ["Bob", 30, "London"],
            ["Charlie", 35, "Tokyo"],
            ["Bob", 30, "London"],
            ["Charlie", 35, "Tokyo"],
            ["Bob", 30, "London"],
            ["Charlie", 35, "Tokyo"],
            ["Bob", 30, "London"],
            ["Charlie", 35, "Tokyo"],
            ["Bob", 30, "London"],
            ["Charlie", 35, "Tokyo"],
            ["Bob", 30, "London"],
            ["Charlie", 35, "Tokyo"],
            ["Bob", 30, "London"],
            ["Charlie", 35, "Tokyo"],
            ["Bob", 30, "London"],
            ["Charlie", 35, "Tokyo"]
        ]

        df = pd.DataFrame(data, columns=["Name", "Age", "City"])
        if df is not None:
            self.table_data = df.values
            self.table_title = df.columns
        self.total_page = int(len(self.table_data) / int(self.page_number)) + 1  # 总页码数
        self.table.setMinimumHeight(400)
        self.flash_data()

    def total_page_count(self):
        """
        重新计算总页数
        :return: 总页数 int
        """
        return int(len(self.table_data) / int(self.page_number)) + 1

    def page_number_changed(self):
        """
        每页条数选择框改变事件
        :return:
        """
        self.page_number = self.page_number_box.currentText()
        self.current_page = 1
        self.flash_data()
        # self.init()
        self.flash_buttons()
        self.flash_page_components()

    def flash_page_components(self):
        """
        重新渲染页码
        :return:
        """
        self.total_page = self.total_page_count()
        self.total_page_text.setText(f'共 {self.total_page} 页')
        if self.current_page == 1:
            self.first.setEnabled(False)
            self.previous.setEnabled(False)
        else:
            self.first.setEnabled(True)
            self.previous.setEnabled(True)
        if self.current_page == self.total_page:
            self.last.setEnabled(False)
            self.follow.setEnabled(False)
        else:
            self.last.setEnabled(True)
            self.follow.setEnabled(True)
        # 如果总页数小于5页，要隐藏几个页码
        btn_list = [self.btn1, self.btn2, self.btn3, self.btn4, self.btn5]
        if self.total_page <= 5:
            for i in range(1, 6):
                if i <= self.total_page:
                    btn_list[i - 1].setVisible(True)
                    # btn_list[i - 1].setEnabled(True)
                    # btn_list[i - 1].setFixedSize(40, 40)
                else:
                    btn_list[i - 1].setVisible(False)
                    # btn_list[i - 1].setEnabled(False)
                    # btn_list[i - 1].setFixedWidth(40)
        else:
            for i in range(1, 6):
                btn_list[i - 1].setVisible(True)
                # btn_list[i - 1].setEnabled(True)
                # btn_list[i - 1].setFixedSize(40, 40)
        # 总页数大于5，查前3页，和最后3页，页码都不变，只有当前页选项框有所改变
        if self.current_page <= 3 or self.total_page - self.current_page <= 3:
            self.flash_buttons()

    def flash_buttons(self):
        """
        重新加载页码数
        :return:
        """
        pages = []
        if self.current_page <= 3:
            pages = [1, 2, 3, 4, 5]
        elif self.total_page - self.current_page <= 5:
            pages = [self.total_page - 4, self.total_page - 3, self.total_page - 2, self.total_page - 1,
                     self.total_page]
        else:
            pages = [self.current_page - 2, self.current_page - 1, self.current_page, self.current_page + 1,
                     self.current_page + 2]
        self.btn1.setText(str(pages[0]))
        self.btn2.setText(str(pages[1]))
        self.btn3.setText(str(pages[2]))
        self.btn4.setText(str(pages[3]))
        self.btn5.setText(str(pages[4]))
        self.set_current_page_style()

    def flash_data(self):
        """
        重新渲染数据
        :return:
        """
        self.table.setRowCount(0)
        self.table.setColumnCount(len(self.table_data[0]))
        self.table.setHorizontalHeaderLabels(self.table_title)
        start_row = (self.current_page - 1) * int(self.page_number)
        end_row = self.current_page * int(self.page_number)
        if len(self.table_data) < end_row:
            end_row = len(self.table_data)
        self.table.setRowCount(end_row - start_row)
        # 这里必须使用切片，大大减少遍历的数量级
        show_list = self.table_data[start_row:end_row]
        for index_row, row in enumerate(show_list):
            for index_col, col in enumerate(row):
                self.table.setItem(index_row, index_col, QTableWidgetItem(str(col)))
        # 调整所有列宽以适应内容
        self.table.resizeColumnsToContents()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MainWindow()
    ex.show()
    sys.exit(app.exec_())
